﻿using System;
using System.IO;
using OpenLS.Spreadsheet.Formats.Biff.Records.Styling;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal struct XfProp
    {
        //private byte[] xfPropDataBlob;

        private XFPropDataBlobType _xfPropType;
        private XFPropValue _value;

        public XFPropDataBlobType Type
        {
            get { return _xfPropType; }
        }

        public XFPropValue Value
        {
            get {
                return _value;
            }
        }

        XFPropValue CreateValue (XFPropDataBlobType type)
        {
            switch (type)
            {

                case XFPropDataBlobType.FillPattern:
                    return new XFPropFillPattern();
                case XFPropDataBlobType.BackgroundColor:
                case XFPropDataBlobType.ForegroundColor:
                    return new XFPropColor();
                case XFPropDataBlobType.GradientFill:
                    return new XFPropGradientFill();
                case XFPropDataBlobType.GradientStop:
                    return new XFPropGradientStop();
                case XFPropDataBlobType.TextColor:
                    return new XFPropColor();
                case XFPropDataBlobType.TopBorder:
                case XFPropDataBlobType.BottomBorder:
                case XFPropDataBlobType.LeftBorder:
                case XFPropDataBlobType.RightBorder:
                case XFPropDataBlobType.DiagonalBorder:
                case XFPropDataBlobType.VerticalBorder:
                case XFPropDataBlobType.HorizontalBorder:
                    return new XFPropBorder();
                case XFPropDataBlobType.DiagonalUp:
                case XFPropDataBlobType.DiagonalDown:
                    return new XFPropBool();
                case XFPropDataBlobType.HorizontalAlignment:
                    return new HorizAlign();
                case XFPropDataBlobType.VerticalAlignment:
                    return new VertAlign();
                case XFPropDataBlobType.TextRotation:
                    return new XFPropTextRotation();
                case XFPropDataBlobType.TextIndentation:
                    return new XFPropUShort();
                case XFPropDataBlobType.ReadingOrder:
                    return new ReadingOrder();
                case XFPropDataBlobType.TextWrapped:
                case XFPropDataBlobType.JustifyDistributed:
                case XFPropDataBlobType.ShrinkToFit:
                case XFPropDataBlobType.CellMerged:
                    return new XFPropBool();
                case XFPropDataBlobType.FontName:
                    return new XFPropLPWideString();
                case XFPropDataBlobType.FontWeight:
                    return new XFPropBold();
                case XFPropDataBlobType.FontUnderline:
                    return new XFPropUnderline();
                case XFPropDataBlobType.Script:
                    return new XFPropScript();
                case XFPropDataBlobType.Italic:
                case XFPropDataBlobType.Strikethrough:
                case XFPropDataBlobType.OutlineStyle:
                case XFPropDataBlobType.ShadowStyle:
                case XFPropDataBlobType.TextCondensed:
                case XFPropDataBlobType.TextExtended:
                    return new XFPropBool();
                case XFPropDataBlobType.CharacterSet:
                case XFPropDataBlobType.FontFamily:
                    return new XFPropByte();
                case XFPropDataBlobType.TextSize:
                    return new XFPropUInt();
                case XFPropDataBlobType.FontScheme:
                    return new XFPropFontScheme();
                case XFPropDataBlobType.NumberFormat:
                case XFPropDataBlobType.FormatIdentifier:
                case XFPropDataBlobType.RelativeTextIndentationLevel:
                    return new XFPropBlob();
                case XFPropDataBlobType.Locked:
                case XFPropDataBlobType.Protected:
                    return new XFPropByte();
                    throw new NotImplementedException();
                default:
                    throw new NotSupportedException();

            }
        }
        public void Read(BinaryReader reader)
        {
#if DEBUG
            ReadWriteChecker.CheckStruct((ref XfProp t, BinaryReader r) => t.Read(r), (ref XfProp t, BinaryWriter w) => t.Write(w), reader, ref this);
#endif

            _xfPropType = (XFPropDataBlobType) reader.ReadUInt16();
            ushort cb = reader.ReadUInt16();
            this._value =  CreateValue(Type);
            _value.Read(reader, cb - 2 - 2);
        }

        public void Write(BinaryWriter writer)
        {
            writer.Write((ushort)this.Type);
            writer.Write(((ushort)(this._value.Length + 2 + 2)));
            this._value.Write(writer);
        }
    }
}